// *** LICENSE HEADER ***
// Filename: ./gameboard.cpp
// This file is part of Nodewarz 0.1
// Nodewarz is a 3d OpenGL strategy game
// Copyright (C) 2007 CZestmyr
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// *** END LICENSE HEADER ***
#include "gameboard.h"

gameBoard::gameBoard() {
    width = height = 0;
    lightmap = 0;
    texture = 0;
    originX = originY = 0;
}

gameBoard::~gameBoard() {
    if (lightmap)
        delete[] lightmap;
    if (texture)
        UnloadTexture(texture);
}

void gameBoard::SetLightManager(lightManager* newManager) {
    theLightManager = newManager;
}

void gameBoard::Redim(int newWidth, int newHeight) {
    //Delete the lightmap if it exists
    if (lightmap)
        delete[] lightmap;
    width = newWidth;
    height = newHeight;
    //Allocate the new lightmap
    lightmap = new GLfloat[(width + 1) *(height + 1) * 3];
    //Set the lightmap to terrain ambient color
    for (int i = 0; i < width + 1; ++i)
        for (int j = 0; j < height + 1; ++j) {
            lightmap[(j*(width+1)+i)*3] = _TERRAIN_AMBIENT_COLOR;
            lightmap[(j*(width+1)+i)*3 + 1] = _TERRAIN_AMBIENT_COLOR;
            lightmap[(j*(width+1)+i)*3 + 2] = _TERRAIN_AMBIENT_COLOR;
        }
    //Set the new board origin
    originX = (float)width / -2.0f;
    originY = (float)height / -2.0f;
}

void gameBoard::LoadTerrainTexture(const char* filename) {
    if (texture)
        UnloadTexture(texture);
    texture = LoadTexture(filename);
}

void gameBoard::UnloadTerrainTexture() {
    if (texture)
        UnloadTexture(texture);
    texture = 0;
}

bool gameBoard::IsInsideTheBoard(float x, float y){
    if (x < originX || x > -originX) return false;
    if (y < originY || y > -originY) return false;
    return true;
}

void gameBoard::Draw(bool showGrid) {
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
    glBindTexture(GL_TEXTURE_2D, texture);
    glDisable(GL_BLEND);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    //Board surface with its lightmap
    for (int j = 0; j < height; ++j) {
        for (int i = 0; i < width; ++i) {
            glBegin(GL_QUADS);
            glColor3fv(lightmap + (j*(width + 1) + i)*3);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(originX + i, originY + j, 0.0f);
            glColor3fv(lightmap + (j*(width + 1) + i + 1)*3);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(originX + i + 1.0f, originY + j, 0.0f);
            glColor3fv(lightmap + ((j + 1)*(width + 1) + i + 1)*3);
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(originX + i + 1.0f, originY + j + 1.0f, 0.0f);
            glColor3fv(lightmap + ((j + 1)*(width + 1) + i)*3);
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(originX + i, originY + j + 1.0f, 0.0f);
            glEnd();
        }
    }

    //Game grid
    if (showGrid) {
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_TEXTURE_2D);
        glColor3f(0.15f, 0.15f, 0.15f);
        for (int j = 0; j <= height; ++j) {
            glBegin(GL_LINES);
            glVertex3f(originX, originY + j, 0.0f);
            glVertex3f(-originX, originY + j, 0.0f);
            glEnd();
        }
        for (int i = 0; i <= width; ++i) {
            glBegin(GL_LINES);
            glVertex3f(originX + i, originY, 0.0f);
            glVertex3f(originX + i, -originY, 0.0f);
            glEnd();
        }
    }
}

void gameBoard::RecalculateLighting(float centerX, float centerY, float radius) {
    if (!theLightManager)
        return;
    float r, g, b, x, y;
    GLfloat* lightmapPointer;
    //Iterate through all the verttices of the lightmap, but...
    for (int j = 0; j <= height; ++j) {
        y = originY + j;
        for (int i = 0; i <= width; ++i) {
            x = originX + i;
            //...recalculate only those terrain vertices that were affected by the change
            if (Distancef(x, y, centerX, centerY) <= radius) {
                theLightManager->GetLightColorAt(x, y, r, g, b);
                lightmapPointer = &lightmap[(j*(width+1)+i)*3];
                r += _TERRAIN_AMBIENT_COLOR;
                g += _TERRAIN_AMBIENT_COLOR;
                b += _TERRAIN_AMBIENT_COLOR;
                Constraintf(r, 0.0f, 1.0f);
                Constraintf(g, 0.0f, 1.0f);
                Constraintf(b, 0.0f, 1.0f);
                lightmapPointer[0] = r;
                lightmapPointer[1] = g;
                lightmapPointer[2] = b;
            }
        }
    }
}
